package net.lqy.aipan.component;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;

import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import net.lqy.aipan.enums.BizCodeEnum;
import net.lqy.aipan.exception.BizException;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * MinIO 文件存储引擎实现类，用于操作对象存储服务（兼容 S3 协议）
 */
@Component
@Slf4j
public class MinioFileStorageEngine implements StorageEngine {

    private static final String CONTENT_TYPE_FORCE_DOWNLOAD = "application/force-download";
    private static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";

    @Autowired()
    private AmazonS3 amazonS3Client;

    /**
     * 判断指定的 Bucket 是否存在
     *
     * @param bucketName Bucket 名称
     * @return 如果存在则返回 true，否则返回 false
     */
    @Override
    public boolean bucketExists(String bucketName) {
        return amazonS3Client.doesBucketExist(bucketName);
    }

    /**
     * 删除指定的 Bucket
     *
     * @param bucketName Bucket 名称
     * @return 如果删除成功返回 true，否则返回 false
     */
    @Override
    public boolean removeBucket(String bucketName) {
        if (amazonS3Client.doesBucketExist(bucketName)) {
            try {
                // 检查存储桶是否为空
                List<S3ObjectSummary> objects = amazonS3Client.listObjects(bucketName).getObjectSummaries();
                if (!objects.isEmpty()) {
                    log.error("存储桶 " + bucketName + " 不为空，无法删除");
                    return false;
                }else {
                    amazonS3Client.deleteBucket(bucketName);
                    return true;
                }
            } catch (Exception e) {
                log.error("删除存储桶失败：{}", bucketName, e);
            }
        }
        return false;
    }

    /**
     * 创建新的 Bucket
     *
     * @param bucketName Bucket 名称
     */
    @Override
    public void createBucket(String bucketName) {
        if (!amazonS3Client.doesBucketExist(bucketName)) {
            amazonS3Client.createBucket(bucketName);
            log.info("Bucket [{}] 已创建", bucketName);
        } else {
            log.error("Bucket [{}] 已存在", bucketName);
            throw new BizException(BizCodeEnum.BUCKET_NOT_EXISTS);
        }
    }

    /**
     * 获取所有 Bucket 列表
     *
     * @return Bucket 列表
     */
    @Override
    public List<Bucket> getAllBuckets() {
        return amazonS3Client.listBuckets();
    }

    /**
     * 列出指定 Bucket 下的所有对象
     *
     * @param bucketName Bucket 名称
     * @return 对象摘要列表
     */
    @Override
    public List<S3ObjectSummary> listObjects(String bucketName) {
        if (amazonS3Client.doesBucketExist(bucketName)) {
            return amazonS3Client.listObjects(bucketName).getObjectSummaries();
        } else {
            log.error("Bucket [{}] 不存在", bucketName);
            throw new BizException(BizCodeEnum.BUCKET_NOT_EXISTS);
        }
    }

    /**
     * 判断指定对象是否存在于 Bucket 中
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @return 如果存在返回 true，否则返回 false
     */
    @Override
    public boolean objectExists(String bucketName, String objectKey) {
        return amazonS3Client.doesObjectExist(bucketName, objectKey);
    }

    /**
     * 从本地文件上传到指定 Bucket
     *
     * @param bucketName     Bucket 名称
     * @param objectKey      对象 Key
     * @param localFileName  本地文件路径
     * @return 上传成功返回 true，否则返回 false
     */
    @Override
    public boolean upload(String bucketName, String objectKey, String localFileName) {
        if (amazonS3Client.doesBucketExist(bucketName)) {
            amazonS3Client.putObject(bucketName, objectKey, new File(localFileName));
            return true;
        }
        return false;
    }

    /**
     * 从 MultipartFile 上传到指定 Bucket
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @param file       上传的文件
     * @return 上传成功返回 true，否则返回 false
     */
    @Override
    public boolean upload(String bucketName, String objectKey, MultipartFile file) {
        if (!amazonS3Client.doesBucketExist(bucketName)) {
            return false;
        }
        try {
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentType(file.getContentType());
            objectMetadata.setContentLength(file.getSize());
            amazonS3Client.putObject(bucketName, objectKey, file.getInputStream(), objectMetadata);
            return true;
        } catch (IOException e) {
            log.error("文件上传失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 删除指定 Bucket 中的对象
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @return 删除成功返回 true，否则返回 false
     */
    @Override
    public boolean delete(String bucketName, String objectKey) {
        if (amazonS3Client.doesBucketExist(bucketName)) {
            amazonS3Client.deleteObject(bucketName, objectKey);
            return true;
        }
        return false;
    }

    /**
     * 获取对象的临时下载链接
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @param timeout    超时时间
     * @param unit       时间单位
     * @return 下载链接 URL 字符串
     */
    @Override
    public String getDownloadUrl(String bucketName, String objectKey, long timeout, TimeUnit unit) {
        try {
            Date expiration = new Date(System.currentTimeMillis() + unit.toMillis(timeout));
            return amazonS3Client.generatePresignedUrl(bucketName, objectKey, expiration).toString();
        } catch (Exception e) {
            log.error("获取下载地址失败: {}", e.getMessage());
            throw new BizException(BizCodeEnum.DOWNLOAD_URL_GENERATE_FAILED);
        }
    }

    /**
     * 将指定对象写入 HttpServletResponse 输出流供下载
     *
     * @param bucketName    Bucket 名称
     * @param objectKey     对象 Key
     * @param response      HTTP 响应对象
     */
    @Override
    public void download2Response(String bucketName, String objectKey, HttpServletResponse response) {
        try (S3Object s3Object = amazonS3Client.getObject(bucketName, objectKey)) {
            String fileName = objectKey.substring(objectKey.lastIndexOf("/") + 1);
            response.setHeader(HEADER_CONTENT_DISPOSITION, "attachment;filename=" + fileName);
            response.setContentType(CONTENT_TYPE_FORCE_DOWNLOAD);
            response.setCharacterEncoding("UTF-8");
            IOUtils.copy(s3Object.getObjectContent(), response.getOutputStream());
        } catch (Exception e) {
            log.error("下载文件失败: {}", e.getMessage());
            throw new BizException(BizCodeEnum.FILE_DOWNLOAD_FAILED);
        }
    }
}
